/* 
 * File:   Arquivo.cpp
 * Author: Pedro
 * 
 * Created on 13 de Agosto de 2010, 08:56
 */

#include "Arquivo.h"
#include "Lexema.h"
#include "../TiposDeLexema.h"
#include "Identificador.h"
#include "ConstanteString.h"
#include "ConstantaNumerica.h"
#include "PalavraReservada.h"
using namespace Texto;

int Arquivo::NumLinha = 1;

Arquivo::Arquivo(string nome) {
    this->nome = nome;   
}

Arquivo::Arquivo(const Arquivo& orig) {
    this->nome = orig.nome;
}

Arquivo::~Arquivo() {
    this->handler.close();
}

string Arquivo::getNomeArquivo() {
    return this->nome;
}

void Arquivo::AbrirArquivo() {
    this->handler.open(this->nome.c_str(), ifstream::in);

    if (!(this->handler.is_open()))
        cout << "erro ao abrir!";
}

char Arquivo::lerCaracter() {
    char c;
    c = this->handler.get();
    if(c=='\n'){
        NumLinha++;
    }
    return c;
}

string Arquivo::lerLinha() {
    string retorno;
    char buffer[4096];
    this->handler.getline(buffer, 4096);
    retorno.assign(buffer);
    NumLinha++;
    return retorno;
}

Lexema* Arquivo::RetornaProximoLexema() {

    Lexema *lexema;
    string retorno = "";
    char lido;

    while (!this->handler.eof() && (lido = this->lerCaracter()) == ' ' || lido == '\n');

    if (this->handler.eof()){
         lexema = new Lexema();
         lexema->assign("<EOF>");
         return lexema;
    }

    retorno += lido;

    if(Lexema::IsSimbolo(lido) && (lido)){

        if (Lexema::IsSimboloDuplo(lido))
        if(Lexema::IsSimbolo(lido = this->lerCaracter()))
           retorno += lido;
        else
            this->handler.seekg(-1,ios_base::cur);
        PalavraReservada  *palavra;
              palavra  = new PalavraReservada();
        palavra->assign(retorno);
        return palavra;

    }

    while ((lido = this->lerCaracter()) != ' ' && lido != '\n' && !this->handler.eof() && !Lexema::IsSimbolo(lido))
            retorno += lido;

       if (Lexema::IsSimbolo(lido)){
           this->handler.seekg(-1,ios_base::cur);

        }

    switch(Lexema::retornaTipo(retorno)){

        case _Identificador:
            lexema = new Identificador();
        break;
        case Constante_string:
            lexema = new ConstanteString();
        break;
        case Constante_Numerica:
            lexema = new ConstantaNumerica();
            break;
        case Palavra_reservada:
            lexema = new PalavraReservada();
            break;
        default:
            lexema = new Lexema();
        break;

    }
    lexema->assign(retorno);
    return lexema;
}

string Arquivo::RetornaProximoLexemaString() {

    string retorno = "";
    char lido;

    while (!this->handler.eof() && (lido = this->lerCaracter()) == ' ' || lido == '\n');

    if (this->handler.eof()){
         return retorno;
    }

    retorno += lido;

    if(Lexema::IsSimbolo(lido)){

        if (Lexema::IsSimboloDuplo(lido))
        if(Lexema::IsSimbolo(lido = this->lerCaracter()))
           retorno += lido;
        else
            this->handler.seekg(-1,ios_base::cur);

        return retorno;

    }

    while ((lido = this->lerCaracter()) != ' ' && lido != '\n' && !this->handler.eof() && !Lexema::IsSimbolo(lido))
            retorno += lido;

       if (Lexema::IsSimbolo(lido)){
           this->handler.seekg(-1,ios_base::cur);

        }

    return retorno;
}

bool Arquivo::fimDoArquivo() {
    return this->handler.eof();
}
